namespace ScrumSprintMonitor.Modules.WorkItemMonitor
{
	#region #using Directives

	using System.Windows.Controls;

	using Extensibility;

	using Infrastructure;
	using Infrastructure.Configuration;
	using Infrastructure.IoC;

	using Microsoft.Practices.Composite.Modularity;
	using Microsoft.Practices.Composite.Regions;
	using Microsoft.Practices.ServiceLocation;
	using Microsoft.Practices.Unity;

	using UI.Wpf.ViewModels;

	using ViewModels;

	using ActivationException = Microsoft.Practices.ServiceLocation.ActivationException;
	using IModule = Microsoft.Practices.Composite.Modularity.IModule;

	#endregion

	[Module(ModuleName = "Work Item Monitor")]
	public class WorkItemMonitorModule : IModule
	{
		private readonly IUnityContainer container;
		private readonly ILogger<WorkItemMonitorModule> logger;
		private readonly IRegionManager regionManager;
		private readonly IResourceManager resourceManager;
		private readonly IServiceLocator serviceLocator;
		private readonly IShellLayoutConfiguration shellLayoutConfiguration;

        public WorkItemMonitorModule(IServiceLocator serviceLocator, IUnityContainer container, IRegionManager regionManager, IResourceManager resourceManager,
		                             IShellLayoutConfiguration shellLayoutConfiguration, ILogger<WorkItemMonitorModule> logger)
		{
			this.serviceLocator = serviceLocator;
            this.container = container;
			this.regionManager = regionManager;
			this.resourceManager = resourceManager;
			this.shellLayoutConfiguration = shellLayoutConfiguration;
			this.logger = logger;

			this.logger.Info("Module starting...");
		}

		#region Implementation of IModule

		public void Initialize()
		{
			RegisterViewsAndServices();

			bool planningMode = this.serviceLocator.GetInstance<IMonitorViewModel>().SprintMode == SprintMode.Planning;

			this.regionManager.RegisterViewWithRegion(RegionNames.PrimaryMonitorRegion, () => this.serviceLocator.GetInstance<IMonitorViewModel>());

			if (this.shellLayoutConfiguration.MultiMonitor || !planningMode)
			{
				this.regionManager.RegisterViewWithRegion(RegionNames.SprintOverviewChartsRegion,
				                                          () => this.serviceLocator.GetInstance<IUserStoryCountChartViewModel>());
				this.regionManager.RegisterViewWithRegion(RegionNames.SprintOverviewChartsRegion,
				                                          () => this.serviceLocator.GetInstance<IBacklogItemCountChartViewModel>());
				this.regionManager.RegisterViewWithRegion(RegionNames.SprintOverviewChartsRegion,
				                                          () => this.serviceLocator.GetInstance<ISprintHoursChartViewModel>());
			}

			this.regionManager.RegisterViewWithRegion(RegionNames.SprintBurndownChartRegion,
			                                          () => this.serviceLocator.GetInstance<ISprintBurndownChartViewModel>());
			this.regionManager.RegisterViewWithRegion(RegionNames.SprintStatisticsRegion, () => this.serviceLocator.GetInstance<ISprintStatsViewModel>());

		    this.regionManager.RegisterViewWithRegion(RegionNames.HorizontalSprintTitleRegion,
		                                              () =>
		                                              this.container.Resolve<ISprintTitleViewModel>(new ParameterOverride("placeholderOrientation",
		                                                                                                                  Orientation.Horizontal)));

		    this.regionManager.RegisterViewWithRegion(RegionNames.VerticalSprintTitleRegion,
		                                              () =>
		                                              this.container.Resolve<ISprintTitleViewModel>(new ParameterOverride("placeholderOrientation",
		                                                                                                                  Orientation.Vertical)));

			if (this.shellLayoutConfiguration.MultiMonitor)
			{
				this.regionManager.RegisterViewWithRegion(RegionNames.SecondaryMonitorRegion, () => this.serviceLocator.GetInstance<ITeamMembersListViewModel>());
			}
			else
			{
				if (planningMode)
				{
					this.regionManager.RegisterViewWithRegion(RegionNames.PrimaryMonitorBottomDockRegion,
					                                          () => this.serviceLocator.GetInstance<ITeamMembersListViewModel>());
				}
				else
				{
					this.regionManager.RegisterViewWithRegion(RegionNames.PrimaryMonitorRightDockRegion,
					                                          () => this.serviceLocator.GetInstance<ITeamMembersListViewModel>());
				}
			}
		}

		#endregion

		protected void RegisterViewsAndServices()
		{
            if (!this.container.IsRegistered<IMonitorViewModel>())
			{
                this.container.RegisterType<IMonitorViewModel, MonitorViewModel>(new ContainerControlledLifetimeManager());
            }

            this.container.RegisterType<ITeamMembersListViewModel, TeamMembersListViewModel>(new ContainerControlledLifetimeManager());
            this.container.RegisterType<ITeamMemberViewModel, TeamMemberViewModel>();
            this.container.RegisterType<IUserStoryCountChartViewModel, UserStoryCountChartViewModel>(new ContainerControlledLifetimeManager());
            this.container.RegisterType<IBacklogItemCountChartViewModel, BacklogItemCountChartViewModel>(new ContainerControlledLifetimeManager());
            this.container.RegisterType<ISprintTitleViewModel, SprintTitleViewModel>();
            this.container.RegisterType<ISprintBurndownChartViewModel, SprintBurndownChartViewModel>(new ContainerControlledLifetimeManager());
            this.container.RegisterType<ISprintStatsViewModel, SprintStatsViewModel>(new ContainerControlledLifetimeManager());
            this.container.RegisterType<ISprintHoursChartViewModel, SprintHoursChartViewModel>(new ContainerControlledLifetimeManager());

			if (this.shellLayoutConfiguration.MultiMonitor)
			{
				this.resourceManager.MergeDictionary(
				                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/TeamMembersMonitorDataTemplate.xaml");
			}
			else
			{
				if (this.serviceLocator.GetInstance<IMonitorViewModel>().SprintMode == SprintMode.Planning)
				{
					this.resourceManager.MergeDictionary(
					                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/TeamMembersWrapPanelDataTemplate.xaml");
				}
				else
				{
					this.resourceManager.MergeDictionary(
					                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/TeamMembersVerticalPanelTemplate.xaml");
				}
			}
			this.resourceManager.MergeDictionary(
			                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/PrimaryMonitorDataTemplate.xaml");
			this.resourceManager.MergeDictionary(
			                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/SprintTitleDataTemplate.xaml");
			this.resourceManager.MergeDictionary(
			                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/SprintChartDataTemplate.xaml");
			this.resourceManager.MergeDictionary(
			                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/SprintStatsDataTemplate.xaml");
			this.resourceManager.MergeDictionary(
			                                     "pack://application:,,,/ScrumSprintMonitor.Modules.WorkItemMonitor;component/DataTemplates/SprintBurndownChartDataTemplate.xaml");
		}
	}
}